import boofcv.alg.InputSanityCheck;
import boofcv.alg.feature.detect.edge.CannyEdge;
import boofcv.alg.feature.detect.edge.EdgeContour;
import boofcv.alg.filter.binary.BinaryImageOps;
import boofcv.alg.filter.binary.Contour;
import boofcv.alg.filter.binary.GThresholdImageOps;
import boofcv.alg.filter.binary.ThresholdImageOps;
import boofcv.factory.feature.detect.edge.FactoryEdgeDetectors;
import boofcv.gui.ListDisplayPanel;
import boofcv.gui.binary.VisualizeBinaryData;
import boofcv.gui.image.ShowImages;
import boofcv.gui.image.VisualizeImageData;
import boofcv.io.UtilIO;
import boofcv.io.image.ConvertBufferedImage;
import boofcv.io.image.UtilImageIO;
import boofcv.struct.ConnectRule;
import boofcv.struct.image.GrayF32;
import boofcv.struct.image.GrayS16;
import boofcv.struct.image.GrayS32;
import boofcv.struct.image.GrayU8;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        String file = "D:\\desktop\\1\\222222_original_grayscaled.png";
        GrayF32 image = UtilImageIO.loadImage(file,GrayF32.class);// 灰度图
//        ShowImages.showWindow(image,"Output1");

        GrayU8 output = new GrayU8(image.width,image.height);

        double threshold = 150;
        ThresholdImageOps.threshold(image, output, (float)threshold, true);// 二值图




        BufferedImage bufferedImage = VisualizeBinaryData.renderBinary(output, false, null);// 渲染 0 1
        ShowImages.showWindow(bufferedImage,"Output2");


        main22(bufferedImage);
    }




    public static void main2(  ) {
        // load and convert the image into a usable format
        BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("particles01.jpg"));

        // convert into a usable format
        GrayF32 input = ConvertBufferedImage.convertFromSingle(image, null, GrayF32.class);
        GrayU8 binary = new GrayU8(input.width, input.height);
        GrayS32 label = new GrayS32(input.width, input.height);

        // Select a global threshold using Otsu's method.
        double threshold = GThresholdImageOps.computeOtsu(input, 0, 255);

        // Apply the threshold to create a binary image
        ThresholdImageOps.threshold(input, binary, (float)threshold, true);

        // remove small blobs through erosion and dilation
        // The null in the input indicates that it should internally declare the work image it needs
        // this is less efficient, but easier to code.
        GrayU8 filtered = BinaryImageOps.erode8(binary, 1, null);
        filtered = BinaryImageOps.dilate8(filtered, 1, null);

        // Detect blobs inside the image using an 8-connect rule
        List<Contour> contours = BinaryImageOps.contour(filtered, ConnectRule.EIGHT, label);

        // colors of contours
        int colorExternal = 0xFFFFFF;
        int colorInternal = 0xFF2020;

        // display the results
        BufferedImage visualBinary = VisualizeBinaryData.renderBinary(binary, false, null);
        BufferedImage visualFiltered = VisualizeBinaryData.renderBinary(filtered, false, null);
        BufferedImage visualLabel = VisualizeBinaryData.renderLabeledBG(label, contours.size(), null);
        BufferedImage visualContour = VisualizeBinaryData.renderContours(contours, colorExternal, colorInternal,
                input.width, input.height, null);

        ListDisplayPanel panel = new ListDisplayPanel();
        panel.addImage(visualBinary, "Binary Original");
        panel.addImage(visualFiltered, "Binary Filtered");
        panel.addImage(visualLabel, "Labeled Blobs");
        panel.addImage(visualContour, "Contours");
        ShowImages.showWindow(panel, "Binary Operations", true);
    }
    public static void main22( BufferedImage image ) {
       // BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("simple_objects.jpg"));

        GrayU8 gray = ConvertBufferedImage.convertFrom(image,(GrayU8)null);
        GrayU8 edgeImage = gray.createSameShape();

        // Create a canny edge detector which will dynamically compute the threshold based on maximum edge intensity
        // It has also been configured to save the trace as a graph.  This is the graph created while performing
        // hysteresis thresholding.
        CannyEdge<GrayU8, GrayS16> canny = FactoryEdgeDetectors.canny(2,true, true, GrayU8.class, GrayS16.class);

        // The edge image is actually an optional parameter.  If you don't need it just pass in null
        canny.process(gray,0.1f,0.3f,edgeImage);

        // First get the contour created by canny
        List<EdgeContour> edgeContours = canny.getContours();
        // The 'edgeContours' is a tree graph that can be difficult to process.  An alternative is to extract
        // the contours from the binary image, which will produce a single loop for each connected cluster of pixels.
        // Note that you are only interested in external contours.
        List<Contour> contours = BinaryImageOps.contourExternal(edgeImage, ConnectRule.EIGHT);

        // display the results
        BufferedImage visualBinary = VisualizeBinaryData.renderBinary(edgeImage, false, null);
        BufferedImage visualCannyContour = VisualizeBinaryData.renderContours(edgeContours,null,
                gray.width,gray.height,null);
        BufferedImage visualEdgeContour = new BufferedImage(gray.width, gray.height,BufferedImage.TYPE_INT_RGB);
        VisualizeBinaryData.render(contours, (int[]) null, visualEdgeContour);

        ListDisplayPanel panel = new ListDisplayPanel();
        panel.addImage(visualBinary,"Binary Edges from Canny");
        panel.addImage(visualCannyContour, "Canny Trace Graph");
        panel.addImage(visualEdgeContour,"Contour from Canny Binary");
        ShowImages.showWindow(panel,"Canny Edge", true);
    }
}
